﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cstring>
#include <fstream>
#include <winsock2.h>
#include <ws2tcpip.h>

// 链接 Winsock 库
#pragma comment(lib, "ws2_32.lib")

// 配置参数（可按需修改）
#define LISTEN_PORT 5174          // 监听端口
#define MAX_CONNECTIONS 5         // 最大等待连接数
#define HTML_FILE_PATH "../251107简单tcp连接/public/index.html"  // HTML 文件路径（相对可执行文件）
#define BUFFER_SIZE 4096          // 读取文件缓冲区大小

// 错误提示（纯 ASCII）
void PrintError(const char* msg) {
    std::cerr << "[Error] " << msg << " | Error Code: " << WSAGetLastError() << std::endl;
}

// 读取 HTML 文件内容，返回文件长度
int ReadHtmlFile(char* buffer, int maxSize) {
    std::ifstream htmlFile(HTML_FILE_PATH, std::ios::in | std::ios::binary);
    if (!htmlFile.is_open()) {
        PrintError("Failed to open HTML file");
        return -1;
    }

    // 读取文件内容到缓冲区
    htmlFile.read(buffer, maxSize - 1);  // 留 1 字节存字符串结束符
    int fileLen = htmlFile.gcount();     // 实际读取的字节数
    buffer[fileLen] = '\0';              // 添加字符串结束符

    htmlFile.close();
    return fileLen;
}

int main() {
    WSADATA wsaData;
    int ret;

    // 1. 初始化 Winsock
    ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (ret != 0) {
        PrintError("WSAStartup failed");
        return 1;
    }

    // 2. 创建 TCP Socket
    SOCKET listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listenSock == INVALID_SOCKET) {
        PrintError("Create socket failed");
        WSACleanup();
        return 1;
    }

    // 3. 绑定端口
    sockaddr_in serverAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(LISTEN_PORT);

    ret = bind(listenSock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
    if (ret == SOCKET_ERROR) {
        PrintError("Bind port failed");
        closesocket(listenSock);
        WSACleanup();
        return 1;
    }

    // 4. 开始监听
    ret = listen(listenSock, MAX_CONNECTIONS);
    if (ret == SOCKET_ERROR) {
        PrintError("Listen failed");
        closesocket(listenSock);
        WSACleanup();
        return 1;
    }

    // 预读取 HTML 文件（启动时读取，避免每次请求都读文件）
    char htmlBuffer[BUFFER_SIZE];
    int htmlLen = ReadHtmlFile(htmlBuffer, BUFFER_SIZE);
    if (htmlLen <= 0) {
        closesocket(listenSock);
        WSACleanup();
        return 1;
    }

    std::cout << "HTTP Server Started! Listen on port: " << LISTEN_PORT << std::endl;
    std::cout << "HTML File Loaded! Size: " << htmlLen << " bytes" << std::endl;
    std::cout << "Local access: http://127.0.0.1:" << LISTEN_PORT << std::endl;
    std::cout << "FRP access: http://124.223.42.84:65174" << std::endl;
    std::cout << "Waiting for connections... (Press Ctrl+C to exit)" << std::endl;

    // 5. 循环处理客户端请求
    while (1) {
        SOCKET clientSock = accept(listenSock, NULL, NULL);
        if (clientSock == INVALID_SOCKET) {
            PrintError("Accept connection failed");
            continue;
        }

        std::cout << "New client connected!" << std::endl;

        // 构建 HTTP 响应（响应头 + 预读取的 HTML 内容）
        char response[BUFFER_SIZE + 256];  // 响应头 + HTML 内容
        sprintf(response,
            "HTTP/1.1 200 OK\r\n"
            "Content-Type: text/html\r\n"
            "Content-Length: %d\r\n"
            "\r\n%s",
            htmlLen, htmlBuffer);

        // 发送响应
        ret = send(clientSock, response, strlen(response), 0);
        if (ret == SOCKET_ERROR) {
            PrintError("Send response failed");
        }
        else {
            std::cout << "Response sent! Total Bytes: " << ret << std::endl;
        }

        closesocket(clientSock);
    }

    // 清理资源（Ctrl+C 退出时不执行）
    closesocket(listenSock);
    WSACleanup();
    return 0;
}